#include <QApplication>
#include <QComboBox>
#include <QFileDialog>
#include <QFrame>
#include <QGridLayout>
#include <QImage>
#include <QLabel>
#include <QLineEdit>
#include <QPainter>
#include <QPushButton>
#include <QSpinBox>
#include <QStackedWidget>
#include <QTimer>
#include <QVBoxLayout>
#include <QWidget>
#include <optional>
#include <qrcodegencpp/qrcodegen.hpp>

#include "QRCodeGeneratorWindow.hpp"

QRCodeGeneratorWindow::QRCodeGeneratorWindow(QMainWindow *parent)
    : QMainWindow(parent)
{
    this->setupUI();
    this->updatePreviewArea();
}

// 更新预览区的二维码
void QRCodeGeneratorWindow::updatePreviewArea()
{
    // 获取纠错等级参数和输入文本
    auto eccLevel  = this->paramSetDialog->getEccLevel();
    auto inputText = std::string{};

    // 根据当前模式选择相应的输入文本
    if (this->textModeRadio->isChecked()) {
        // 如果是文本编码模式，则读取文本输入框的内容
        inputText = this->inputTextEditor->toPlainText().trimmed().toStdString();
    } else if (this->wifiModeRadio->isChecked()) {
        // 如果是WIFI编码模式，则生成WIFI字符串
        inputText = this->wifiInfoInputEdit->getWifiInfoString().toStdString();
    }

    // 如果输入文本为空，则设置默认字符串
    if (inputText.empty()) {
        inputText = "Please input";
    }
    // 尝试生成二维码对象
    auto qrcode = this->generateQrCodeObject(inputText.c_str(), eccLevel);

    // 如果生成失败，则显示错误信息并返回
    if (not qrcode) {
        this->statusBar->showMessage("Input is too long for the selected ECC level");
        return;
    }

    // 更新状态信息
    this->statusBar->showMessage(
        QString("Version: %1, Size: %2x%2")
            .arg(qrcode->getVersion())
            .arg(qrcode->getSize()));

    // 渲染图像
    auto qrcodeImage = this->renderQrCode(*qrcode,
                                          this->paramSetDialog->getPixelSize(),
                                          this->paramSetDialog->getBorderSize());
    // 清理并重设图像
    this->previewArea->clear();
    this->previewArea->load(qrcodeImage);
}

void QRCodeGeneratorWindow::clearInput()
{
    // 手动清空输入文本、预览区
    this->inputTextEditor->clear();
    this->previewArea->clear();

    this->wifiInfoInputEdit->clear();
}

// 保存图像到文件
void QRCodeGeneratorWindow::saveAsPng()
{
    const auto &qrcodeImage = this->previewArea->getOriginalImage();
    if (not qrcodeImage.isNull()) {
        auto filename = QFileDialog::getSaveFileName(
            this,
            "Save QR Code",
            "qrcodegen",
            "PNG Image (*.png);;All Files (*)");

        if (not filename.isEmpty()) {
            if (qrcodeImage.save(filename)) {
                this->statusBar->showMessage("Saved to " + filename);
            } else {
                this->statusBar->showMessage("Failed to save to " + filename);
            }
        }
    } else {
        this->statusBar->showMessage("QR Code is empty");
    }
}

void QRCodeGeneratorWindow::setupUI()
{
    // 设置窗口标题
    this->setWindowTitle("QR Code Generator");

    // 设置图像预览区
    this->previewArea = new ImagePreviewArea{this};
    this->previewArea->setAlignment(Qt::AlignCenter);
    this->previewArea->setFrameStyle(QFrame::Box);
    this->previewArea->setMinimumSize(300, 300);
    this->previewArea->setSizePolicy(QSizePolicy::Expanding,
                                     QSizePolicy::Expanding);

    // 设置面板切换 RadioButton
    this->textModeRadio = new QRadioButton("Text", this);
    this->textModeRadio->setChecked(true);
    this->wifiModeRadio = new QRadioButton("WIFI", this);
    // 任意一个按钮被点击时更新预览
    QObject::connect(
        this->textModeRadio,
        &QRadioButton::clicked,
        this,
        &QRCodeGeneratorWindow::updatePreviewArea);
    QObject::connect(
        this->wifiModeRadio,
        &QRadioButton::clicked,
        this,
        &QRCodeGeneratorWindow::updatePreviewArea);

    auto modeSwitchRadioButtonWidget       = new QWidget{this};
    auto modeSwitchRadioButtonWidgetLayout = new QHBoxLayout{modeSwitchRadioButtonWidget};
    modeSwitchRadioButtonWidgetLayout->addWidget(this->textModeRadio);
    modeSwitchRadioButtonWidgetLayout->addWidget(this->wifiModeRadio);
    modeSwitchRadioButtonWidgetLayout->setAlignment(Qt::AlignCenter);

    // 设置文本编码模式部分 - 只有一个文本输入框
    this->inputTextEditor = new QTextEdit{this};
    this->inputTextEditor->setPlaceholderText("Input here");
    this->inputTextEditor->setMaximumHeight(100);
    QObject::connect(
        this->inputTextEditor,
        &QTextEdit::textChanged,
        this,
        &QRCodeGeneratorWindow::updatePreviewArea);

    // 设置WIFI编码模式部分 - 包含 SSID、密码、加密方式、隐藏模式等输入框
    this->wifiInfoInputEdit = new WifiInfoInputEdit{this};
    QObject::connect(
        this->wifiInfoInputEdit,
        &WifiInfoInputEdit::infoChanged,
        this,
        &QRCodeGeneratorWindow::updatePreviewArea);

    // stack 存储两个界面
    auto modeSeitchWidget = new QStackedWidget{this};
    modeSeitchWidget->addWidget(this->inputTextEditor);
    modeSeitchWidget->addWidget(this->wifiInfoInputEdit);
    QObject::connect(
        this->textModeRadio,
        &QRadioButton::clicked,
        [modeSeitchWidget]() {
            modeSeitchWidget->setCurrentIndex(0);
        });
    QObject::connect(
        this->wifiModeRadio,
        &QRadioButton::clicked,
        [modeSeitchWidget]() {
            modeSeitchWidget->setCurrentIndex(1);
        });

    // 按钮部分
    auto clearButtonIcon = QApplication::style()->standardIcon(QStyle::SP_DialogResetButton);
    this->clearButton    = new QPushButton{clearButtonIcon, "Clear", this};
    QObject::connect(
        this->clearButton,
        &QPushButton::clicked,
        this,
        &QRCodeGeneratorWindow::clearInput);

    // 参数设置按钮、保存为图片按钮
    this->settingsButton = new QPushButton{"Settings", this};
    this->paramSetDialog = new ParamSetDialog;
    QObject::connect(
        this->settingsButton,
        &QPushButton::clicked,
        this->paramSetDialog,
        &ParamSetDialog::show);

    QObject::connect(
        this->paramSetDialog,
        &ParamSetDialog::accepted,
        this,
        &QRCodeGeneratorWindow::updatePreviewArea);
    QObject::connect(
        this->paramSetDialog,
        &ParamSetDialog::apply,
        this,
        &QRCodeGeneratorWindow::updatePreviewArea);

    auto saveIcon    = QApplication::style()->standardIcon(QStyle::SP_DialogSaveButton);
    this->saveButton = new QPushButton(saveIcon, "Save", this);
    QObject::connect(
        this->saveButton,
        &QPushButton::clicked,
        this,
        &QRCodeGeneratorWindow::saveAsPng);

    // 设置底部控制按钮
    auto controlButtonWidget       = new QWidget{this};
    auto controlButtonWidgetLayout = new QHBoxLayout{controlButtonWidget};
    controlButtonWidgetLayout->addWidget(this->clearButton);
    controlButtonWidgetLayout->addWidget(this->settingsButton);
    controlButtonWidgetLayout->addWidget(this->saveButton);
    controlButtonWidgetLayout->setAlignment(Qt::AlignCenter);

    // 主布局
    auto mainWidget       = new QWidget{this};
    auto mainWidgetLayout = new QGridLayout{mainWidget};
    mainWidgetLayout->addWidget(this->previewArea, 0, 0);
    mainWidgetLayout->addWidget(modeSwitchRadioButtonWidget, 1, 0);
    mainWidgetLayout->addWidget(modeSeitchWidget, 2, 0);
    mainWidgetLayout->addWidget(controlButtonWidget, 3, 0);

    // 第一行自适应，其他行固定高度
    mainWidgetLayout->setRowStretch(0, 1);
    mainWidgetLayout->setRowStretch(1, 0);
    mainWidgetLayout->setRowStretch(2, 0);
    mainWidgetLayout->setRowStretch(3, 0);

    // 设置窗口主部件
    this->setCentralWidget(mainWidget);

    // 设置底部状态栏
    this->statusBar = new QStatusBar{this};
    this->statusBar->showMessage("Ready");
    this->setStatusBar(this->statusBar);
}

// 根据参数生成二维码对象，若输入过长则返回 std::nullopt
std::optional<qrcodegen::QrCode> QRCodeGeneratorWindow::generateQrCodeObject(const char *text, qrcodegen::QrCode::Ecc eccLevel)
{
    try {
        auto qrcode = qrcodegen::QrCode::encodeText(text, eccLevel);
        return qrcode;
    } catch (const qrcodegen::data_too_long &e) {
        return std::nullopt;
    }
}

// 根据二维码对象渲染图形
QImage QRCodeGeneratorWindow::renderQrCode(const qrcodegen::QrCode &qrCode, int pixelSize, int borderSize)
{
    // 计算图片大小
    auto qrcodeSize = qrCode.getSize();
    auto totalSize  = (qrcodeSize + 2 * borderSize) * pixelSize;
    auto image      = QImage{totalSize, totalSize, QImage::Format_ARGB32};
    image.fill(this->paramSetDialog->getBackColor());

    // 绘制二维码
    auto painter = QPainter{&image};
    painter.setPen(Qt::NoPen); // 无边框
    painter.setBrush(this->paramSetDialog->getFrontColor());

    for (auto y = 0; y < qrcodeSize; y++) {
        for (auto x = 0; x < qrcodeSize; x++) {
            if (qrCode.getModule(x, y) == true) {
                painter.drawRect(
                    (borderSize + x) * pixelSize,
                    (borderSize + y) * pixelSize,
                    pixelSize,
                    pixelSize);
            }
        }
    }

    return image;
}
